#include "StdAfx.h"
#include "main_object.h"
#include "dll_manager.h"
#include "alloc.h"
#include <interface/log_interface.h>
#include <utility/api_tools.h>
#include <utility/ini_op.h>


void 
sys_event_mgr::insert(int event_type, int* events, int num, dll_module* dll)
{
	auto_lock_type __mon(this->mutex_);

	event_table_type& t = this->groups_[event_type];
	for( int i = 0; i < num; ++i )
	{
		t[ events[i] ].push_back(dll);
	}
}

void 
sys_event_mgr::__dispatch_sys_event(int event_type, int ev, WPARAM wparam, LPARAM lparam, aot::tt::sys_event_param_t* sep)
{
	aot_log_trace(AOT_LM_TRACE, "sys_event_mgr::__dispatch_sys_event()");
	aot_log_debug(AOT_LM_DEBUG, "__ event_type = %d, ev = %d", event_type, ev);

	do
	{
		if( this->is_stop_ )
		{
			break;
		}

		auto_lock_type __mon(this->mutex_);

		event_group_type::iterator it = this->groups_.find(event_type);
		if( it == this->groups_.end() )
		{
			break;
		}

		event_table_type::iterator it2 = it->second.find(ev);
		if( it2 == it->second.end() )
		{
			break;
		}

		std::list<dll_module*>& lst = it2->second;
		int size = lst.size();
		int i = 0;

		if( size == 0 )
		{
			break;
		}

		if( sep && size > 1 )
		{	
			for( i = 0; i < size - 1; ++i )
			{
				if( sep->wparam )
					sep->wparam->inc_ref();
				if( sep->lparam )
					sep->lparam->inc_ref();
			}
		}

		std::list<dll_module*>::iterator it3 = lst.begin();
		i = 0;
		for( ;it3 != lst.end(); ++it3 )
		{
			++i;
			aot_log_debug(AOT_LM_TRACE, " enter into %s process sys event event_type = %d, ev = %d", 
				(*it3)->obj()->module_name(), event_type, ev);

			if( -1 == (*it3)->obj()->on_sys_event(event_type, ev, wparam, lparam, sep) )
			{
				aot_log_debug(AOT_LM_TRACE, " leaving %s process sys event event_type = %d, ev = %d", 
					(*it3)->obj()->module_name(), event_type, ev);

				int c = size - i;
				if( sep && c > 0 )
				{	
					for( i = 0; i < c; ++i )
					{
						if( sep->wparam )
							sep->wparam->destroy();
						if( sep->lparam )
							sep->lparam->destroy();
					}
				}
				aot_log_debug(AOT_LM_ALERT, "[%s] have been not pass the event to next dll: event_type = %d, ev = %d", (*it3)->obj()->interface_name(), event_type, ev);
				return;
			}
			aot_log_debug(AOT_LM_TRACE, " leaving %s process sys event event_type = %d, ev = %d", 
				(*it3)->obj()->module_name(), event_type, ev);
		}
		/// in this case, all the events have been processed, so we return as normal 
		return;
	}while(0);

	/// the event had not been processed? we print it out...
	if( sep )
	{
		if( sep->wparam )
			sep->wparam->destroy();
		if( sep->lparam )
			sep->lparam->destroy();
	}

	aot_log_debug(AOT_LM_ALERT, "app lost event: event_type = %d, ev = %d", event_type, ev);
}

/* - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */

struct __cmd_to_func
{
	__cmd_to_func(aot::tt::command_t* c, aot::tt::result_t* r)
	{
		cmd_ = c;
		ret_ = r;
	}
	void operator ()(dll_module* p)
	{
		p->obj()->on_command(cmd_, ret_);
	}
	aot::tt::command_t* cmd_;
	aot::tt::result_t* ret_;
};

struct __putq_to_func
{
	__putq_to_func(aot::tt::message_t* m, long tm_out, aot::tt::result_t* r)
	{
		msg_ = m;
		ret_ = r;
		tm_out_ = tm_out;
	}
	void operator ()(dll_module* p)
	{
		p->obj()->on_putq(msg_, tm_out_, ret_);
	}
	aot::tt::message_t* msg_;
	aot::tt::result_t* ret_;
	long tm_out_;
};

struct __query_func
{
	__query_func(void** r, const TCHAR* k)
	{
		ret_ = r;
		key_ = k;
	}
	bool operator ()(dll_module* p)
	{
		if( p && p->obj() )
		{
			return p->obj()->query_interface(this->ret_, this->key_);
		}
		return false;
	}
	void**	ret_;
	const TCHAR* key_;
};

/* - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */

main_object::main_object()
{
	this->impl_ = NULL;

	this->shr_alloc_ = new share_alloc();
	this->shr_alloc_->need_destroy_ = false;
// 	this->glb_data_ = new global_data_wrapper;
}

main_object::~main_object()
{
	if( this->shr_alloc_ )
	{
		delete this->shr_alloc_;
	}
}

BOOL 
main_object::release()
{
// 	if( this->glb_data_ )
// 	{
// 		delete this->glb_data_;
// 		this->glb_data_ = NULL;
// 	}
	return TRUE;
}

void 
main_object::destroy()
{
	/// not delete this
}

bool 
main_object::regist_to(const void* rg_param, int type, aot::tt::result_t* rg_ret)
{
	AFX_MANAGE_STATE(AfxGetAppModuleState());

	// 	switch( type )
	// 	{
	// 	case e_regist_frame_group:
	// 		{
	// 			if( NULL == this->impl_->page_main_ )
	// 				return false;
	// 
	// 			if( s_cmd_id > e_leftframe_cmd_end )
	// 				return false;
	// 
	// 			regist_frame_group_param_t* p = (regist_frame_group_param_t*)rg_param;
	// 			dll_module* dll = (dll_module*)p->token;
	// 			std::string dllname = dll->obj()->interface_name();
	// 			if( p->token )
	// 			{
	// 				if( p->img_fn && p->img_fn[0] )
	// 				{
	// 					int ret = this->impl_->page_main_->wnd_leftframe_toolbar_.add_item(p->img_fn, 
	// 						p->label ? p->label : "", dllname.c_str(), s_cmd_id, aot::e_leftbar_btn_dllmoudle, p->canmgr, aot::e_leftbar_btn_reg_from_dll);
	// 					if( ret < 0 )
	// 					{
	// 						aot_log_error(AOT_LM_ERROR, "%s", "regist_frame_group failed !");
	// 						return false;
	// 					}
	// 					regist_frame_group_param_t* rp = new regist_frame_group_param_t;
	// 					*rp = *p;
	// 					dll->data_ = rp;
	// 					
	// 					if( ret == 0 )
	// 					{
	// 						s_cmd_id++;
	// 					}
	// 					if( ret == 0 || ret == 1 )
	// 					{
	// 						int commandid = 0;
	// 						ret = this->impl_->page_main_->wnd_leftframe_toolbar_.get_command_id(dllname.c_str(), commandid);
	// 						if( ret == 0 )
	// 						{
	// 							dll->key_ = commandid;
	// 						}
	// 					}
	// 					return true;
	// 				}
	// 			}
	// 			aot_log_error(AOT_LM_ERROR, "%s", "regist_frame_group failed !");
	// 			return false;
	// 		}
	// 		break;
	// 	case e_regist_frame_top:
	// 		{
	// 			regist_frame_top_t* p = (regist_frame_top_t*)rg_param;
	// 			if( p->token )
	// 			{
	// 				dll_module* dll = (dll_module*)p->token;
	// 				dll->data_ = new regist_frame_top_t;
	// 				memcpy(dll->data_, p, sizeof(regist_frame_top_t));
	// 				return true;
	// 			}
	// 			else
	// 			{
	// 				aot_log_error(AOT_LM_ERROR, "%s", "regist_frame_top failed !");
	// 				return false;
	// 			}
	// 		}
	// 		break;
	// 	case e_regist_frame_bottom:
	// 		{
	// 			regist_frame_bottom_t* p = (regist_frame_bottom_t*)rg_param;
	// 			if( p->token )
	// 			{
	// 				dll_module* dll = (dll_module*)p->token;
	// 				dll->data_ = new regist_frame_bottom_t;
	// 				memcpy(dll->data_, p, sizeof(regist_frame_bottom_t));
	// 				return true;
	// 			}
	// 			else
	// 			{
	// 				aot_log_error(AOT_LM_ERROR, "%s", "regist_frame_bottom failed !");
	// 				return false;
	// 			}
	// 		}
	// 		break;
	// 	case e_regist_trans_msg:
	// 		{
	// 			regist_trans_msg_t* p = (regist_trans_msg_t*)rg_param;
	// 			if( p->token && p->is_trans_msg )
	// 			{
	// 				dll_module* dll = (dll_module*)p->token;
	// 				trans_msg_.push_back(dll);
	// 				return true;
	// 			}
	// 		}
	// 		break;
	// 	case e_regist_sys_event:
	// 		{
	// 			regist_sys_event_t* p = (regist_sys_event_t*)rg_param;
	// 			if( p && p->token && p->event_lst && p->event_num > 0 )
	// 			{
	// 				this->event_mgr_.insert(p->event_type, p->event_lst, p->event_num, (dll_module*)p->token);
	// 				return true;
	// 			}
	// 		}
	// 		break;
	// 	default:
	// 		return false;
	// 	}
	return true;
}

bool 
main_object::query_interface(void** out, const TCHAR* key)
{
	if( key == NULL || key[0] == 0 )
		return false;

	if( 0 == strncmp("idll.", key, strlen("idll.")) )
	{
		dll_module* dll = dll_manager::instance()->find_all(key);
		if( dll )
		{
			dll->obj()->inc_ref();
			*out = dll->obj();
			return true;
		}

		return false;
	}

	if( 0 == strcmp("ixml_parser", key) )
	{
		dll_module* dll = dll_manager::instance()->find_component("idll.xml_parser.dll");
		if( dll )
		{
			return dll->obj()->query_interface(out, key);
		}

		return false;
	}

	if( 0 == strcmp("ires_parser", key) )
	{
		dll_module* dll = dll_manager::instance()->find_component("idll.xml_parser.dll");
		if( dll )
		{
			return dll->obj()->query_interface(out, key);
		}

		return false;
	}

	if( 0 == strcmp("ishare_alloc", key) )
	{
		*out = (aot::tt::ialloc*)this->shr_alloc_;

		return true;
	}

	if( 0 == strcmp("ilog", key) )
	{
		dll_module* dll = dll_manager::instance()->find_component("idll.log.dll");
		if( dll )
		{
			return dll->obj()->query_interface(out, key);
		}

		return false;
	}

	__query_func func(out, key);
	if( dll_manager::instance()->find_all_if(func) )
		return true;

	return false;
}

bool 
main_object::query_interface_ex(void** out, const TCHAR* dll_name, const TCHAR* key)
{
	dll_module* dll = dll_manager::instance()->find_all(dll_name);
	if( dll )
	{
		return  dll->obj()->query_interface(out, key);;
	}

	return false;
}

bool 
main_object::query_interface_by_iid_ex(void** out, const TCHAR* dll_name, int key)
{
	dll_module* dll = dll_manager::instance()->find_all(dll_name);
	if( dll )
	{
		return  dll->obj()->query_interface_by_iid(out, key);;
	}

	return false;
}


int
main_object::putq_to(const TCHAR* key, aot::tt::message_t* msg, long tm/* = -1*/, aot::tt::result_t* ret/* = NULL*/)
{
	// 	if( 0 == strcmp("imain", key) )
	// 	{
	// 		AFX_MANAGE_STATE(AfxGetAppModuleState());
	// 
	// 		return -1;
	// 	}
	// 
	// 	if( 0 == strncmp("idll.", key, strlen("idll.")) )
	// 	{
	// 		dll_module* dll = dll_manager::instance()->find_all(key);
	// 		if( dll )
	// 		{
	// 			return dll->obj()->on_putq(msg, tm, ret);
	// 		}
	// 
	// 		return -1;
	// 	}
	// 
	// 	if( 0 == strncmp("*.*", key, strlen("*.*")) )
	// 	{
	// 		__putq_to_func fun(msg, tm, ret);
	// 		dll_manager::instance()->for_each_all(fun);
	// 		return 0;
	// 	}

	return -1;
}

/// block model
int
main_object::command_to(const TCHAR* key, aot::tt::command_t* cmd, aot::tt::result_t* ret/* = NULL*/)
{

	// 	if( 0 == strcmp("imain", key) )
	// 	{
	// 		AFX_MANAGE_STATE(AfxGetAppModuleState());
	// 
	// 		if( cmd && cmd->val == 100 && cmd->type == 100 )
	// 		{
	// 			this->impl_->switch_to(1);
	// 			return 0;
	// 		}
	// 		if( cmd && cmd->val == 101 && cmd->type == 101 )
	// 		{
	// 			//COLORREF color = *((COLORREF*)cmd->data);
	// 
	// 			//CBCGPVisualManager2007::SetCustomColor( color );
	// 
	// 			//CBCGPVisualManager::GetInstance()->RedrawAll();
	// 			return 0;
	// 		}
	// 		if( cmd && cmd->val == GET_MAIN_HWND && cmd->type == ADDRBOOK_MSG )
	// 		{
	// 			HWND *pHwnd = (HWND *)ret->data;
	// 			*pHwnd = this->impl_->m_hWnd;
	// 			return 0;
	// 		}
	// 		if( cmd && cmd->type == WM_GLB_UI_GET_LEFTBAR_SEL )
	// 		{
	// 			aot::tt::istr* dllname = (aot::tt::istr*)ret->data;
	// 			//CString dllname = this->impl_->page_main_->get_curr_sel_dll();
	// 			dllname->assign(this->impl_->page_main_->get_curr_sel_dll());
	// 			return 0;
	// 		}
	// 		if( cmd && cmd->type == WM_GLB_UI_SAVE_SETTING )
	// 		{
	// 			::PostMessage(impl_->m_hWnd, WM_GLB_UI_SAVE_SETTING, cmd->type, 0);
	// 		}
	// 		if( cmd && cmd->type == WM_GLB_UI_HIDE_LEFT_TOOLBAR )
	// 		{
	// 			::PostMessage(impl_->page_main_->GetSafeHwnd(), WM_GLB_UI_HIDE_LEFT_TOOLBAR, cmd->val, 0);
	// 		}
	// 		if( cmd && cmd->type == WM_GLB_UI_SHOW_LEFT_TOOLBAR )
	// 		{
	// 			::PostMessage(impl_->page_main_->GetSafeHwnd(), WM_GLB_UI_SHOW_LEFT_TOOLBAR, cmd->val, 0);
	// 		}
	// 		if( cmd && cmd->type == WM_GLB_UI_SHOW_UI_MANAGER )
	// 		{
	// 			::PostMessage(impl_->page_main_->GetSafeHwnd(), WM_GLB_UI_SHOW_UI_MANAGER, cmd->val, 0);
	// 		}
	// 		if( cmd && cmd->type == WM_GLB_UI_EXIT_TATA )
	// 		{
	// 			::PostMessage(impl_->GetSafeHwnd(), WM_GLB_UI_EXIT_TATA, cmd->val, 0);
	// 		}
	// 		if( cmd && cmd->type == WM_GLB_IMCHAT_TO_TRAY_MGR_CHAT_MSG )
	// 		{
	// 			aot_log_debug(AOT_LM_DEBUG, "WM_GLB_IMCHAT_TO_TRAY_MGR_CHAT_MSG userid %s;msgkey %s;msgtype %d;dlgtype %d", 
	// 				(const TCHAR*)cmd->to, (const TCHAR*)cmd->user_data_ptr[0], cmd->user_data[0], cmd->val);
	// 			impl_->tray_msg_.play_sound();
	// 			if( cmd->user_data[0] == aot::e_cmd_shake_msg )
	// 			{
	// 				int lock_status = dll_manager::instance()->get_glb_data()->cfg_mgr_.get_lock_app();
	// 				if( aot::e_unlock_app == lock_status )
	// 				{
	// 					cmd->type = WM_GLB_TRAY_MGR_TO_IMCHAT_CHAT_MSG;
	// 					aot::tt::iobj_auto_ptr<aot::common_dlg::icommon_dlg_manager> common_dlg_mgr;
	// 					int ret = dll_manager::instance()->get_main_obj()->query_interface_ex(common_dlg_mgr, "idll.common_dlg.dll", "icommon_dlg_manager");
	// 					if( ret )
	// 					{
	// 						common_dlg_mgr->show_taskdlg_shark_msg((const TCHAR*)cmd->to);
	// 					}
	// 					impl_->tray_msg_.pop_im_msg((const TCHAR*)cmd->to, cmd->val);
	// 					command_to("idll.imchat.dll", cmd);
	// 				}
	// 			}
	// 			else if( cmd->user_data[0] == aot::e_cmd_file_trans_request || cmd->user_data[0] == aot::e_cmd_offline_file_request )
	// 			{
	// 				BOOL auto_recv = FALSE;
	// 				if( aot::e_checkbox_val_select_check == this->glb_data_->cfg_mgr_.get_recv_file_all() )
	// 				{
	// 					auto_recv = TRUE;
	// 				}
	// 
	// 				if( !auto_recv )
	// 				{
	// 					if ( aot::e_checkbox_val_select_check == this->glb_data_->cfg_mgr_.get_recv_file_colleauge() )
	// 					{
	// 						if ( this->glb_data_->enterprise_->is_member_in_ent((const TCHAR*)cmd->to) )
	// 						{
	// 							auto_recv = TRUE;
	// 						}
	// 					}
	// 					if( !auto_recv )
	// 					{
	// 						if ( aot::e_checkbox_val_select_check == this->glb_data_->cfg_mgr_.get_recv_file_friend() )
	// 						{
	// 							if ( this->glb_data_->buddy_mgr_->find((const TCHAR*)cmd->to) )
	// 							{
	// 								auto_recv = TRUE;
	// 							}
	// 						}
	// 					}
	// 				}
	// 				if( auto_recv )
	// 				{
	// 					cmd->type = WM_GLB_TRAY_MGR_TO_IMCHAT_CHAT_MSG;
	// 					impl_->tray_msg_.pop_im_msg((const TCHAR*)cmd->to, cmd->val);
	// 					command_to("idll.imchat.dll", cmd);
	// 				}
	// 				else
	// 				{
	// 					push_tray_msg(cmd);
	// 				}
	// 			}
	// 			else
	// 			{
	// 				push_tray_msg(cmd);
	// 			}
	// 		}
	// 		if( cmd && cmd->type == WM_GLB_IMCHAT_TO_TRAY_OPEN_CHAT_WND )
	// 		{
	// 			aot_log_debug(AOT_LM_DEBUG, "WM_GLB_IMCHAT_TO_TRAY_OPEN_CHAT_WND userid %s;msgkey %s;msgtype %d;dlgtype %d", 
	// 				(const TCHAR*)cmd->to, (const TCHAR*)cmd->user_data_ptr[0], cmd->user_data[0], cmd->val);
	// 			CString userid = (const TCHAR*)cmd->to;
	// 			impl_->tray_msg_.pop_im_msg(userid, cmd->val);
	// 		}
	// 		if( cmd && cmd->type == WM_GLB_UI_CONFIG_CHANGE )
	// 		{
	// 			
	// 		}
	// 		if( cmd && cmd->type == WM_GLB_UI_GET_UI_CONFIG )
	// 		{
	// 			switch( cmd->val )
	// 			{
	// 			case aot::e_ui_config_change_ishide:
	// 				{
	// 					ret->ret = this->ui_cfg_.ishide;
	// 					break;
	// 				}
	// 			}
	// 		}
	// 		if( cmd && cmd->type == WM_GLB_MAIN_MAXBTN_CLICK)
	// 		{
	// 			::PostMessage(impl_->GetSafeHwnd(), WM_GLB_MAIN_MAXBTN_CLICK, 0, 0);
	// 		}
	// 		return -1;
	// 	}
	// 
	// 	if( 0 == strncmp("idll.", key, strlen("idll.")) )
	// 	{
	// 		dll_module* dll = dll_manager::instance()->find_all(key);
	// 		if( dll )
	// 		{
	// 			return dll->obj()->on_command(cmd, ret);
	// 		}
	// 		return -1;
	// 	}
	// 
	// 	if( 0 == strncmp("*.*", key, strlen("*.*")) )
	// 	{
	// 		__cmd_to_func fun(cmd, ret);
	// 		dll_manager::instance()->for_each_all(fun);
	// 		return 0;
	// 	}

	return -1;
}

void 
main_object::dispatch_sys_event(int event_type, int ev, WPARAM wparam, LPARAM lparam, aot::tt::sys_event_param_t* sep)
{

	this->event_mgr_.dispatch_sys_event(event_type, ev, wparam, lparam, sep);
}

bool bFindFile(LPCSTR lpFileName)
{
	WIN32_FIND_DATA FindFileData;
	HANDLE hFind;
	hFind = FindFirstFile(lpFileName, &FindFileData);
	if (hFind == INVALID_HANDLE_VALUE) 
	{
		return (false);
	} 
	else 
	{
		FindClose(hFind);
		return (true);
	}
}

BOOL 
main_object::read_app_data_path()
{
	aot::tt::utility::ini_op ini;
	this->app_path_ = aot::tt::utility::get_app_path().c_str();
	this->app_root_path_ = this->app_path_ + "..\\";

	ini.file_name((this->app_path_ + "\\simba.ini"));
	this->root_data_path_ = ini.read("simba", "root_data_path", this->app_root_path_).c_str();
	this->config_data_path_ = this->root_data_path_ + "config\\";
	this->user_data_path_ = this->root_data_path_ + "user\\";
	this->all_user_data_path_ = this->user_data_path_ + "alluser\\";
	this->temp_data_path_ = this->root_data_path_ + "temp\\";
	this->app_data_path_ = this->app_root_path_ + "data\\";

	if ( !aot::tt::utility::dir_exist(this->root_data_path_))
	{
		aot::tt::utility::dir_create(this->root_data_path_);
		aot::tt::utility::dir_create(this->config_data_path_);
		aot::tt::utility::dir_create(this->user_data_path_);
		aot::tt::utility::dir_create(this->all_user_data_path_);

	}
	else
	{
		if ( !aot::tt::utility::dir_exist( this->config_data_path_ ))
		{
			aot::tt::utility::dir_create(this->config_data_path_);
		}

		if ( !aot::tt::utility::dir_exist( this->user_data_path_ ))
		{
			aot::tt::utility::dir_create(this->user_data_path_);
		}

		if ( !aot::tt::utility::dir_exist( this->all_user_data_path_ ))
		{
			aot::tt::utility::dir_create(this->all_user_data_path_);
		}
	}

	CString web_srv_path = this->config_data_path_ + "web_srv.ini";
	CString src_web_srv_path = this->app_data_path_ + "web_srv.ini";
	CopyFile(src_web_srv_path, web_srv_path, TRUE);

	CString exist_file, new_file_name;
	exist_file = this->app_data_path_ + "\\ui_config.ini";
	new_file_name = this->config_data_path_ + "\\ui_config.ini";
	CopyFile(exist_file, new_file_name, TRUE);

	exist_file = this->app_data_path_ + "\\simba_update.ini";
	new_file_name = this->config_data_path_ + "\\simba_update.ini";
	CopyFile(exist_file, new_file_name, TRUE);

	return TRUE;
}

